import {
  CallHandler,
  ExecutionContext,
  Injectable,
  NestInterceptor,
} from '@nestjs/common';
import { Observable } from 'rxjs';
import { tap, map } from 'rxjs/operators';
import * as requestIp from 'request-ip';
import {nanoid} from "nanoid";
import {globalAsyncLocalStorage} from "../utils/utils";
import { LoggerService } from '@/common/logger/logger.service';

@Injectable()
export class GlobalInterceptor implements NestInterceptor {
  constructor(private readonly loggerService: LoggerService) {}

  log(message: string, req: any){
    const ip = requestIp.getClientIp(req);
    this.loggerService.log(
      `[${ip}${(()=>{
        if(req.user){
          return ` userUuid:${req.user.uuid}`
        }
        if(req.admin){
          return ` adminUuid:${req.admin.uuid}`;
        }
        return ''
      })()}] ${message}`,
      GlobalInterceptor.name,
    )
  }

  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    const now = Date.now();
    const req = context.switchToHttp().getRequest();
    globalAsyncLocalStorage.enterWith({
      requestId: req.headers['x-request-id'] ?? nanoid(), // 这里也可以从header上取，实现全链路
    })
    this.log(`Request start: ${req.method} ${req.url}`, req);

    if (Object.keys(req.body).length !== 0) {
      let requestBodyStr;
      try {
        requestBodyStr = JSON.stringify(req.body, null, 4);
      } catch (e) {
        requestBodyStr = '';
      }
      if (requestBodyStr) {
        this.log(`RequestBody: \n${requestBodyStr}`, req);
      }
    }
    return next.handle().pipe(
        map(data=>{
          // 如果是导出接口，需要判断直接返回
          /* if(){
            return data;
          } */
          return {
            code: 0,
            message: 'success',
            data,
          }
        }),
        tap(() => {
          this.log(`Request end: ${req.method} ${req.url} ${Date.now() - now}ms`, req);
        }),
    );
  }
}
